﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using TC.WEB.Site.Models;
using TC.WEB.Site.Core;
using System.Drawing;
using System.Text;
using System.Dynamic;
using TC.WEB.Site;
using System.Text.RegularExpressions;
using TC.WEB.Site.Models.Tools;

namespace TC.SSO.Server.Controllers
{
    public class AuthController : Controller
    {
        /// <summary>
        /// 是否启用验证码登录
        /// </summary>
        private bool ValidateCode
        {
            get
            {
                if (Session[ValidateCodeKey] == null)
                {
                    return false;
                }
                return Convert.ToBoolean(Session[ValidateCodeKey]);
            }
            set
            {
                Session[ValidateCodeKey] = value;
            }
        }

        /// <summary>
        /// 终端 
        /// </summary>
        private int Terminal
        {
            get
            {
                if (Session[TerminalKey] == null)
                {
                    return 1;
                }
                return Convert.ToInt32(Session[TerminalKey]);
            }
            set
            {
                Session[TerminalKey] = value;
            }
        }

        private bool IsMobile
        {
            get
            {
                return HttpContext.Request.Browser.IsMobileDevice;
            }
        }

        /// <summary>
        /// 中英文 转换
        /// </summary>
        /// <param name="cn"></param>
        /// <returns></returns>
        public static string _T(dynamic text)
        {
            return TC.WEB.Site.Languages.LanguageConfig._T((string)(text.ToString()));
        }

        public static string _T(dynamic cn, dynamic en)
        {
            return TC.WEB.Site.Languages.LanguageConfig._T((string)(cn.ToString()), (string)(en.ToString()));
        }

        public const string CookieKey = "_user_token_key";
        public const string CookiePrivateKey = "_user_private_token_key";
        public const string ValidateCodeKey = "_validate_code_key";
        public const string TerminalKey = "_terminal_key";

        /// <summary>
        /// 设置终端
        /// </summary>
        /// <param name="validate">是否启用验证码</param>
        /// <param name="terminal">终端 1.Web 2.Mobile 3.MoblieWeb 4.Desktop 5.第三方</param>
        private void SetTerminal(bool validate,int terminal)
        {
            this.ValidateCode = validate;
            this.Terminal = terminal;
        }
        //
        // GET: /Login/

        public ActionResult Index()
        {
            return View("BuildNet");
        }

        /// <summary>
        /// 新平台登录页
        /// </summary>
        /// <param name="fc"></param>
        /// <returns></returns>
        public ActionResult BuildNet(FormCollection fc)
        {
            this.SetTerminal(true,IsMobile?3: 1);

            if (IsMobile)
            {
                return CheckLogin("BuildNetMobile", fc);
            }
            return CheckLogin("BuildNet", fc);
        }

        public ActionResult GreenNkit(FormCollection fc)
        {
            this.SetTerminal(true, IsMobile ? 3 : 1);
            if (IsMobile)
            {
                return CheckLogin("BuildNetMobile", fc);
            }
            return CheckLogin("GreenNkit", fc);
        }

        /// <summary>
        /// 工程电讯登录页
        /// </summary>
        /// <param name="fc"></param>
        /// <returns></returns>
        public ActionResult Gcdx(FormCollection fc)
        {
            this.SetTerminal(true, IsMobile ? 3 : 1);
            
            if (IsMobile)
            {
                return CheckLogin("BuildNetMobile", fc);
            }

            #region 项目阶段菜单加载
            var rdModel = BaseModel.M<Reseach_DictModel>();
            var arr = new String[] { "DictName_CN", "DictName_EN", "OrderSN" };
            List<SelectListItem> stages = new List<SelectListItem>();
            var l1stages = rdModel.getProjectDic("ProjectStage", arr);
            Dictionary<string, List<dynamic>> arrayinfo = new Dictionary<string, List<dynamic>>();
            foreach (var item in l1stages)
            {
                var subObj = rdModel.getProjectDic(item.DictName_EN, arr);
                arrayinfo.Add(item.DictName_CN, subObj);
            }
            ViewBag.arr1 = arrayinfo;
            #endregion

            #region 项目类别菜单加载

            var categoryModel = BaseModel.M<Research_ProjectCategoryModel>();
            var arr2 = new String[] { "CategoryId", "ParentId", "CategoryName_CN", "CategoryName_EN" };
            var l1category = categoryModel.getCategory(arr2);
            Dictionary<string, List<dynamic>> arrayinfo2 = new Dictionary<string, List<dynamic>>();
            foreach (var item in l1category)
            {
                var subObj = categoryModel.getSubCategory(item.CategoryId, arr2);
                arrayinfo2.Add(item.CategoryName_CN, subObj);
            }
            ViewBag.proCategory = arrayinfo2;
            #endregion

            return CheckLogin("ebulletin", fc);
        }

        #region 登录

        ActionResult CheckLogin(string viewName, FormCollection fc)
        {
            ViewBag.ErrorMessage = string.Empty;
            string action = (Request["action"] ?? "").ToLower();
            if (action.Equals("submit"))
            {
                return Login(viewName, fc);
            }

            HttpCookie hc = Request.Cookies[CookieKey];
            if (hc != null)
            {
                string str = hc == null ? Session[CookieKey].ToString() : hc.Value;
                string token = Security.DecryptString(str, CookiePrivateKey).Split('|')[0];//解密Token
                if (!string.IsNullOrEmpty(token))
                {
                    //检验Token状态
                    var m = BaseModel.M<UserAccountTokenModel>();
                    var r = m.GetTokenState(token);
                    if (r.Success && r.Value == 1)
                    {
                        return Redirect(GetRedirect(token));
                    }
                }
                hc.Expires = DateTime.Now.AddDays(-1);
                Response.Cookies.Add(hc);
            }

            return View(viewName);
        }

        ActionResult Login(string viewName, FormCollection fc)
        {
            string userName = fc["txtUserName"] ?? "",
                   userPassword = fc["txtUserPassword"] ?? "";
            string pass = userPassword;
            userPassword = BaseModel.M<UserModel>().getPassword(userPassword);


            bool isLoginAnyway = fc["isLoginAnyway"] == "1", isAutoLogin = fc["chkAutoLogin"] == "1";

            //如果启用了验证
            if (this.ValidateCode)
            {
                if (Session["vCode"] == null || fc["vCode"] == null || fc["vCode"].ToLower() != Session["vCode"].ToString())
                {
                    ViewBag.UserName = userName;
                    ViewBag.UserPassword = pass;
                    ViewBag.ErrorMessage = _T("验证码错误");
                    return View(viewName);
                }
            }
            var br = BaseModel.M<UserBlankListModel>().CheckIsIn(Request.ServerVariables["REMOTE_ADDR"], 4);//检查ip地址
            if (br.Value)
            {
                BaseModel.M<UserLoginLogModel>().AddLoginLog(0, userName, pass, "IP异常登录", Request);
                ViewBag.UserName = userName;
                ViewBag.UserPassword = pass;
                ViewBag.ErrorMessage = _T("非法登录!");
                return View(viewName);
            }
            var m = BaseModel.M<UserAccountTokenModel>();
            var r = m.Login(userName, userPassword, this.Terminal, isLoginAnyway);

            int uid = 0;
            if (r.Success)
            {
                var user = m.GetUserInfo(r.Value.Token);
                if (!user.Success)//错误处理
                {
                    Ocor.Logger.LogWriter.Write(Ocor.Logger.LogLevel.Debug, "Login", user.Message);
                    ViewBag.UserName = userName;
                    ViewBag.UserPassword = pass;
                    ViewBag.ErrorMessage = user.Message;
                    return View(viewName);
                }
                uid = user.Value.UserId;
                pass = "";
                r.Message = "正常登录";
            }
            BaseModel.M<UserLoginLogModel>().AddLoginLog(uid, userName, pass, r.Message, Request);
            if (!r.Success)
            {
                ViewBag.UserName = userName;
                ViewBag.UserPassword = pass;
                ViewBag.ErrorMessage = r.Message;
                return View(viewName);
            }

            HttpCookie hc = new HttpCookie(CookieKey);
            hc.Value = Security.EncryptString(string.Format("{0}|{1}", r.Value.Token, Tools.ConvertDateTimeInt(DateTime.Now)), CookiePrivateKey);
            if (isAutoLogin)
            {
                hc.Expires = DateTime.Now.AddDays(7);
            }
            Response.Cookies.Add(hc);


            //判断是否需要 绑定手机号
            /*
            var userinfo = BaseModel.M<UserModel>().getOneEq(new { UserName = userName, UserPass = userPassword }, "UserMobile","IsPay");
            if (userinfo != null && string.IsNullOrWhiteSpace(Convert.ToString(userinfo.UserMobile)) && userinfo.IsPay)
            {
                ViewBag.isbind = "false";
                ViewBag.Token = r.Value.Token;
                ViewBag.Redirect = GetRedirect(r.Value.Token);
                return View(viewName);
            }
            */
            return Redirect(GetRedirect(r.Value.Token));
        }

        string GetRedirect(string token)
        {
            string redirect = string.IsNullOrEmpty(Request["redirect"]) ? "/" : Request["redirect"],
                   state = Request.QueryString["state"] ?? "";//客户端传回来的state参数
            Log.Instance.Debug(string.Format("redirect:{0}", redirect));
            redirect = System.Text.RegularExpressions.Regex.Replace(redirect, @"&?token=([^&]*)", "");//去除源字符串中带有的无效Token
            if (!string.IsNullOrWhiteSpace(state))
            {
                redirect = System.Text.RegularExpressions.Regex.Replace(redirect, @"&?state=([^&]*)", "");//去除源字符串中带有的无效State
            }
            if (!string.IsNullOrWhiteSpace(state))
            {
                if (redirect.IndexOf("?") != -1)
                {
                    redirect = string.Format("{0}&token={1}&state={2}", redirect, token, state);
                }
                else
                {
                    redirect = string.Format("{0}?token={1}&state={2}", redirect, token, state);
                }
            }
            else
            {
                if (redirect.IndexOf("?") != -1)
                {
                    redirect = string.Format("{0}&token={1}", redirect, token);
                }
                else
                {
                    redirect = string.Format("{0}?token={1}", redirect, token);
                }
            }
            return redirect;
        }

        #endregion

        public ActionResult Logout()
        {
            HttpCookie hc = Request.Cookies[CookieKey];
            if (hc != null)
            {
                string token = Security.DecryptString(hc.Value, CookiePrivateKey).Split('|')[0];//解密Token
                var m = BaseModel.M<UserAccountTokenModel>();
                var r = m.Logout(token);
                if (r.Success)
                {
                    System.Text.StringBuilder sb = new System.Text.StringBuilder();
                    string url = string.Empty;
                    foreach (var config in SitesConfig.GetConfig())
                    {
                        if (config.Url.IndexOf("?") != -1)
                        {
                            url = config.Url + string.Format("&token={0}", token);
                        }
                        else
                        {
                            url = config.Url + string.Format("?token={0}", token);
                        }
                        sb.AppendFormat("<iframe src='{0}' style='display:none'></iframe>", url);
                        sb.AppendLine();
                    }
                    ViewBag.LogoutSites = sb.ToString();
                }
                hc.Expires = DateTime.Now.AddDays(-1);
                Response.Cookies.Add(hc);
            }
            return View();
        }
        /// <summary>
        /// 绑定手机号
        /// </summary>
        /// <param name="fc"></param>
        /// <returns></returns>
        public ActionResult bindMobile(FormCollection fc)
        {
            try
            {
                TC.WEB.Site.Models.UserModel um = BaseModel.M<TC.WEB.Site.Models.UserModel>();
                var m = BaseModel.M<UserAccountTokenModel>();
                string codeValue = fc["codeValue"] ?? "";
                string phone = fc["PhoneNo"] ?? "";
                phone = phone.Trim();
                if (!ValidCode.IsValid(phone, codeValue))
                {
                    return Json(new { s = 1, msg = _T("验证码不正确!") });
                }
                Regex rx = new Regex("^(\\+([0-9]{1,6})|([0-9]{1,6}))?([\\-\\ ])?(\\d){1,4}?(\\-)?(\\d){7,8}(\\-)?(\\d){0,4}?$");
                if (!rx.IsMatch(phone.Trim()))
                {
                    return Json(new { s = 1, msg = _T("手机号码格式不正确！") });
                }

                string token = fc["token"] ?? "";
                if (string.IsNullOrWhiteSpace(token))
                {
                    return Json(new { s = 1, msg = _T("参数不正确！") });
                }
                var user = m.GetUserInfo(token);
                if (user.Success)
                {
                    um.saveEq(new { UserMobile = phone.Trim() }, new { Id = user.Value.UserId });
                    return Json(new { s = 0 });
                }
                return Json(new { s = 1, msg = _T("参数不正确！") });
            }
            catch (Exception ex)
            {
                Ocor.Logger.LogWriter.Write(ex, "");
                throw ex;
            }
        }
        /// <summary>
        /// 验证码
        /// </summary>
        /// <returns></returns>
        public ActionResult vvcodeImg()
        {
            Session["vCode"] = null;
            string code = GenerateCheckCode();
            Session["vCode"] = code.ToLower();
            return this.CreateCheckCodeImageNew(code);
        }

        private string GenerateCheckCode()
        {
            int number;
            char code;
            string checkCode = String.Empty;

            System.Random random = new Random();
            for (int i = 0; i < 5; i++)
            {
                number = random.Next();

                if (number % 2 == 0)
                    code = (char)('1' + (char)(number % 10));
                else
                    code = (char)('A' + (char)(number % 26));
                if (code == 'O')
                {
                    number = random.Next();
                    if (number % 2 == 0)
                        code = (char)('1' + (char)(number % 10));
                    else
                        code = (char)('A' + (char)(number % 26));
                }
                checkCode += code.ToString();
            }
            return checkCode;
        }

        #region 手机号，发送验证码验证


        private string[] getRemoteIps()
        {
            List<string> ips = new List<string>();
            //如果客户端使用了代理服务器，则利用HTTP_X_FORWARDED_FOR找到客户端IP地址
            string userHostAddress = "";
            if (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null)
            {
                userHostAddress = Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString().Split(',')[0].Trim();
            }
            //否则直接读取REMOTE_ADDR获取客户端IP地址
            if (!string.IsNullOrEmpty(userHostAddress))
            {
                ips.Add(userHostAddress);
            }
            userHostAddress = Request.ServerVariables["REMOTE_ADDR"];
            //前两者均失败，则利用Request.UserHostAddress属性获取IP地址，但此时无法确定该IP是客户端IP还是代理IP
            if (!string.IsNullOrEmpty(userHostAddress))
            {
                ips.Add(userHostAddress);
            }
            return ips.ToArray();
        }

        /// <summary>
        /// 启用手机验证，登陆时，发送验证码给用户
        /// </summary>
        /// <returns></returns>
        public JsonResult MobileCode(FormCollection form)
        {
            if (Session["__session_client"] == null)
            {
                return Json(new { s = 1, msg = _T("错误的请求！") });
            }
            string result = string.Empty;
            string PhoneNo = form["PhoneNo"] ?? "";
            PhoneNo = PhoneNo.Trim();
            Regex rx = new Regex("^(\\+([0-9]{1,6})|([0-9]{1,6}))?([\\-\\ ])?(\\d){1,4}?(\\-)?(\\d){7,8}(\\-)?(\\d){0,4}?$");
            if (!rx.IsMatch(PhoneNo))
            {
                return Json(new { s = 1, msg = _T("手机号码格式不正确！") });
            }
            var blank = TC.WEB.Site.Core.BaseModel.M<UserBlankListModel>().CheckIsIn(PhoneNo, 1);
            if (blank.Value)
            {
                return Json(new { s = 1, msg = _T("该手机号码不可用！") });
            }
            //验证用户名和密码是否存在
            TC.WEB.Site.Models.UserModel um = new TC.WEB.Site.Models.UserModel();

            dynamic dataUserName = um.getUserNameByValue(new { UserMobile = PhoneNo });//通过手机号称获取用户ID
            if (dataUserName != null)//手机号是否已经存在
            {
                return Json(new { s = 1, msg = _T("该手机号已被注册！") });
            }
            string code = ValidCode.GenMobileCode(PhoneNo);

            if (string.IsNullOrWhiteSpace(code))
            {
                return Json(new { s = 1, msg = _T("请间隔1分钟！") });
            }

            var smsLogModel = new SystemSMSLogModel();
            string[] ips = this.getRemoteIps();
            foreach (string ip in ips)
            {
                if (smsLogModel.getIpCount(ip, DateTime.Now.Date, DateTime.Now.Date) > 20)
                {
                    return Json(new { s = 1, msg = _T("您今天发送了太多的短信！") });
                }
            }

            string msgtemp = System.Configuration.ConfigurationManager.AppSettings["VcodeMsgTemplate"];
            string msg = string.Format(msgtemp, code);
            string msgerror;
            foreach (string ip in ips)
            {
                smsLogModel.insertOne(ip, PhoneNo.Trim(), DateTime.Now);
            }
            if (MailHelper.SendMobileMsg(msg, PhoneNo.Trim(), out msgerror))
            {
                return Json(new { s = 0 });
            }
            return Json(new { s = 1, msg = msgerror });
        }

        #endregion

        private FileContentResult CreateCheckCodeImageNew(string checkCode)
        {
            if (checkCode == null && checkCode.Trim() == String.Empty)
                checkCode = "1234";
            Bitmap image = new Bitmap((int)Math.Ceiling((checkCode.Length * 16.5)), 40);
            Graphics g = Graphics.FromImage(image);
            try
            {
                //生成随机生成器
                Random random = new Random();
                //清空图片背景色
                g.Clear(Color.White);
                //画图片的背景噪音线
                for (int i = 0; i < 25; i++)
                {
                    int x1 = random.Next(image.Width);
                    int x2 = random.Next(image.Width);
                    int y1 = random.Next(image.Height);
                    int y2 = random.Next(image.Height);

                    g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2);
                }
                //System.Drawing.FontStyle.Italic
                Font font = new System.Drawing.Font("Arial", 16, (System.Drawing.FontStyle.Bold));
                System.Drawing.Drawing2D.LinearGradientBrush brush = new System.Drawing.Drawing2D.LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Blue, Color.DarkRed, 1.2f, true);
                g.DrawString(checkCode, font, brush, 3, 6.5f);

                //画图片的前景噪音点
                for (int i = 0; i < 100; i++)
                {
                    int x = random.Next(image.Width);
                    int y = random.Next(image.Height);

                    image.SetPixel(x, y, Color.FromArgb(random.Next()));
                }
                //画图片的边框线
                g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                image.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
                Response.ClearContent();
                Response.ContentEncoding = Encoding.GetEncoding("gb2312");
                return File(ms.ToArray(), "image/Gif");
            }
            finally
            {
                g.Dispose();
                image.Dispose();
            }
        }

        protected override void OnException(ExceptionContext filterContext)
        {
            Ocor.Logger.LogWriter.Write(filterContext.Exception, filterContext.HttpContext.Request.RawUrl);
            base.OnException(filterContext);
        }
    }

}
